package com.wanban.tools

import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.text.TextUtils
import okhttp3.*
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import retrofit2.converter.scalars.ScalarsConverterFactory
import java.io.File
import java.util.concurrent.TimeUnit

object RetrofitTools {

    private var BASE_URL = "http://ctaid.coincoinwin.com/"

    // 本地测试
//    private val BASE_URL = "http://172.18.1.201:8083/"
    // 全局测试
//    private val BASE_URL = "http://124.65.176.126:8882/"
    private var okHttpClient: OkHttpClient? = null
    private var version: Int = 1
    private var channel: String = "unknown"
    private val PLATFORM = "mobile-android"

    fun init(context: Context) {
//        if (BuildConfig.DEBUG) {
//            BASE_URL = "http://124.65.176.126:8882/"
//        }
        channel = getMetaValue(context)
        version = getVersionCode(context)
        okHttpClient = initOkHttpClient(context)
    }

    private val retrofit: Retrofit by lazy {
        val baseUrl = BASE_URL
        return@lazy Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient!!)
            //设置 Json 转换器
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

    }

    fun <T> getApi(service: Class<T>): T {
        return retrofit.create(service)
    }

    fun <T> getStringApi(service: Class<T>): T {
        val baseUrl = BASE_URL
        val retrofit = Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient!!)
            .addConverterFactory(ScalarsConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()
        return retrofit.create(service)
    }

    private fun initOkHttpClient(context: Context): OkHttpClient {
        val readTime = 15
        val writeTime = 15
        val connectTime = 15
        val builder = OkHttpClient.Builder()
        // cache文件位置和大小
        val cacheSize = 104857600 // 100M
        val cacheDirectory = context.externalCacheDir // /data/user/0/com.movies.mobiletv/cache/
        val fileCache = File(cacheDirectory, "json")
        if (!fileCache.exists()) {
            fileCache.mkdirs()
        }
        val cache = Cache(fileCache, cacheSize.toLong())
        builder.cache(cache)

        builder.connectTimeout(connectTime.toLong(), TimeUnit.SECONDS)
        builder.readTimeout(readTime.toLong(), TimeUnit.SECONDS)
        builder.writeTimeout(writeTime.toLong(), TimeUnit.SECONDS)
        builder.retryOnConnectionFailure(true)

        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        builder.addInterceptor(loggingInterceptor)

        builder.addInterceptor {
            val original = it.request()
            val newRequest = original.newBuilder()
                .addHeader("version", version.toString())
                .addHeader("channel", channel)
                .addHeader("platform", PLATFORM)
                .build()
            return@addInterceptor it.proceed(newRequest)
        }

        builder.addInterceptor(object : Interceptor {

            private fun getForceCacheRequest(request: Request): Request {
                return request.newBuilder()
                    .removeHeader("Pragma")
                    .cacheControl(CacheControl.FORCE_CACHE)
                    .build()
            }

            override fun intercept(chain: Interceptor.Chain): Response {
                val request = chain.request()
                val cacheControl = request.cacheControl
                return if (TextUtils.isEmpty(cacheControl.toString())) {
                    chain.proceed(request)
                } else {
                    val requestCache = getForceCacheRequest(request)
                    var response = chain.proceed(requestCache)
                    // 先确认是否有缓存可用
                    if (response.code == 200) { // 有缓存
                        // 先确认当前缓存是否已经超时
                        if (System.currentTimeMillis() - response.receivedResponseAtMillis >= 1000 * cacheControl.maxAgeSeconds) { // 超时
                            response = chain.proceed(chain.request())
                        }

                    } else {
                        response = chain.proceed(chain.request())
                    }
                    return response
                }
            }
        })
        // 重试
//        builder.addInterceptor(RetryInterceptor(3))
        return builder.build()
    }


    @Suppress("DEPRECATION")
    private fun getVersionCode(context: Context): Int {
        val manager = context.packageManager//获取包管理器
        try {
            //通过当前的包名获取包的信息
            val info = manager.getPackageInfo(context.packageName, 0)//获取包对象信息
            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
                info.longVersionCode.toInt()
            } else {
                info.versionCode
            }

        } catch (e: PackageManager.NameNotFoundException) {
            e.printStackTrace()
        }
        return 0
    }


    /**
     * 获取 MetaValue
     * @param context 此处习惯性的设置为activity，实际上context就可以
     * @return 如果没有获取成功，那么返回值为空
     */
    @Suppress("DEPRECATION")
    private fun getMetaValue(context: Context?): String {
        if (context == null) {
            return "unknown"
        }
        var channelName = "unknown"
        try {
            val packageManager = context.packageManager
            if (packageManager != null) {
                //注意此处为ApplicationInfo 而不是 ActivityInfo,因为友盟设置的meta-data是在application标签中，而不是某activity标签中，所以用ApplicationInfo
                val applicationInfo =
                    packageManager.getApplicationInfo(
                        context.packageName,
                        PackageManager.GET_META_DATA
                    )
                if (applicationInfo.metaData != null) {
                    channelName = applicationInfo.metaData.get("CHANNEL_VALUE").toString()
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return channelName
    }


}